#define DEBUG
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ICSharpCode.TextEditor.Actions;
using ICSharpCode.TextEditor.Document;
using ICSharpCode.TextEditor.Gui.CompletionWindow;

namespace ICSharpCode.TextEditor
{
    [ToolboxItem(false)]
    public class TextArea : Control
    {
        private bool disposed;

        private bool toolTipActive;

        private bool hiddenMouseCursor = false;

        private bool mouseDownState = false;

        private Rectangle toolTipRectangle;

        private Point mouseCursorHidePosition;

        private Point virtualTop = new Point(0, 0);

        private TextEditorScrollBar vScrollBar;

        private TextEditorScrollBar hScrollBar;

        private TextAreaControl motherTextAreaControl;

        private TextEditorControl motherTextEditorControl;

        private List<BracketHighlightingSheme> bracketshemes = new List<BracketHighlightingSheme>();

        private TextAreaClipboardHandler textAreaClipboardHandler;

        private bool autoClearSelection = false;

        private bool doHandleMousewheel = true;

        private List<AbstractMargin> leftMargins = new List<AbstractMargin>();

        private TextView textView;

        private GutterMargin gutterMargin;

        private FoldMargin foldMargin;

        private IconBarMargin iconBarMargin;

        private SelectionManager selectionManager;

        private Caret caret;

        internal Point mousepos = new Point(0, 0);

        private static string oldToolTip;

        private AbstractMargin lastMouseInMargin;

        private static DeclarationViewWindow toolTip;

        private AbstractMargin updateMargin = null;

        internal object showContextMenuEventObject = new object();

        private int FirstPhysicalLine => VirtualTop.Y / textView.FontHeight;

        internal TextEditorScrollBar VScrollBar => vScrollBar;

        internal TextEditorScrollBar HScrollBar => hScrollBar;

        internal ImageLayout ImageLayout => motherTextEditorControl.ImageLayout;

        internal Image backgroundImage => motherTextEditorControl.BackgroundImage;

        [Browsable(false)]
        public bool MouseDownState => mouseDownState;

        [Browsable(false)]
        public IList<AbstractMargin> LeftMargins => leftMargins.AsReadOnly();

        public TextEditorControl MotherTextEditorControl => motherTextEditorControl;

        public TextAreaControl MotherTextAreaControl => motherTextAreaControl;

        public SelectionManager SelectionManager => selectionManager;

        public Caret Caret => caret;

        public TextView TextView => textView;

        public GutterMargin GutterMargin => gutterMargin;

        public FoldMargin FoldMargin => foldMargin;

        public IconBarMargin IconBarMargin => iconBarMargin;

        public Encoding Encoding => motherTextEditorControl.Encoding;

        public int MaxVScrollValue
        {
            get
            {
                int result = 0;
                checked
                {
                    if ((Document.GetVisibleLine(Document.TotalNumberOfLines) + 1) * TextView.FontHeight > TextView.DrawingPosition.Height)
                    {
                        result = (Document.GetVisibleLine(Document.TotalNumberOfLines) + 1) * TextView.FontHeight - TextView.DrawingPosition.Height;
                    }
                    return result;
                }
            }
        }

        public int MaxHScrollValue
        {
            get
            {
                int num = 0;
                checked
                {
                    for (int i = 0; i < Document.GetVisibleLine(Document.TotalNumberOfLines); i++)
                    {
                        if (Document.FoldingManager.IsLineVisible(i))
                        {
                            LineSegment lineSegment = Document.GetLineSegment(i);
                            num = Math.Max(num, TextView.GetVisualColumnFast(lineSegment, lineSegment.Length));
                        }
                    }
                    if (num + 2 > TextView.VisibleColumnCount)
                    {
                        num = num + 2 - TextView.VisibleColumnCount;
                    }
                    return num;
                }
            }
        }

        public Point VirtualTop
        {
            get
            {
                return virtualTop;
            }
            set
            {
                Point point = new Point(value.X, Math.Min(MaxVScrollValue, Math.Max(0, value.Y)));
                if (virtualTop != point)
                {
                    virtualTop = point;
                    motherTextAreaControl.VScrollBar.Value = virtualTop.Y;
                    Invalidate();
                }
                caret.UpdateCaretPosition();
            }
        }

        public bool AutoClearSelection
        {
            get
            {
                return autoClearSelection;
            }
            set
            {
                autoClearSelection = value;
            }
        }

        [Browsable(false)]
        public IDocument Document => motherTextEditorControl.Document;

        public TextAreaClipboardHandler ClipboardHandler => textAreaClipboardHandler;

        public ITextEditorProperties TextEditorProperties => motherTextEditorControl.TextEditorProperties;

        public bool DoHandleMousewheel
        {
            get
            {
                return doHandleMousewheel;
            }
            set
            {
                doHandleMousewheel = value;
            }
        }

        public bool EnableCutOrPaste
        {
            get
            {
                if (motherTextAreaControl == null)
                {
                    return false;
                }
                if (SelectionManager.HasSomethingSelected)
                {
                    return !SelectionManager.SelectionIsReadonly;
                }
                return !IsReadOnly(Caret.Offset);
            }
        }

        public event ToolTipRequestEventHandler ToolTipRequest;

        public event KeyEventHandler KeyEventHandler;

        public event DialogKeyProcessor DoProcessDialogKey;

        public event EventHandler ShowContextMenuHandler
        {
            add
            {
                base.Events.AddHandler(showContextMenuEventObject, value);
            }
            remove
            {
                base.Events.RemoveHandler(showContextMenuEventObject, value);
            }
        }

        public void InsertLeftMargin(int index, AbstractMargin margin)
        {
            leftMargins.Insert(index, margin);
            Refresh();
        }

        public TextArea(TextEditorControl motherTextEditorControl, TextAreaControl motherTextAreaControl)
        {
            this.motherTextAreaControl = motherTextAreaControl;
            this.motherTextEditorControl = motherTextEditorControl;
            vScrollBar = motherTextAreaControl.VScrollBar;
            hScrollBar = motherTextAreaControl.HScrollBar;
            caret = new Caret(this);
            selectionManager = new SelectionManager(Document, this);
            textAreaClipboardHandler = new TextAreaClipboardHandler(this);
            base.ResizeRedraw = true;
            SetStyle(ControlStyles.OptimizedDoubleBuffer, value: true);
            SetStyle(ControlStyles.Opaque, value: false);
            SetStyle(ControlStyles.ResizeRedraw, value: true);
            SetStyle(ControlStyles.Selectable, value: true);
            textView = new TextView(this);
            gutterMargin = new GutterMargin(this);
            foldMargin = new FoldMargin(this);
            iconBarMargin = new IconBarMargin(this);
            leftMargins.AddRange(new AbstractMargin[3] { iconBarMargin, gutterMargin, foldMargin });
            OptionsChanged();
            new TextAreaMouseHandler(this).Attach();
            new TextAreaDragDropHandler().Attach(this);
            bracketshemes.Add(new BracketHighlightingSheme('{', '}'));
            bracketshemes.Add(new BracketHighlightingSheme('(', ')'));
            bracketshemes.Add(new BracketHighlightingSheme('[', ']'));
            caret.PositionChanged += SearchMatchingBracket;
            Document.TextContentChanged += TextContentChanged;
            Document.FoldingManager.FoldingsChanged += DocumentFoldingsChanged;
        }

        public void UpdateMatchingBracket()
        {
            SearchMatchingBracket(null, null);
        }

        private void TextContentChanged(object sender, EventArgs e)
        {
            Caret.Position = new TextLocation(0, 0);
            SelectionManager.SelectionCollection.Clear();
            Document.GuidelinesManager.Update(this);
        }

        private void SearchMatchingBracket(object sender, EventArgs e)
        {
            if (!TextEditorProperties.ShowMatchingBracket)
            {
                textView.Highlight = null;
                return;
            }
            int num = -1;
            int num2 = -1;
            if (textView.Highlight != null && textView.Highlight.OpenBrace.Y >= 0 && textView.Highlight.OpenBrace.Y < Document.TotalNumberOfLines)
            {
                num = textView.Highlight.OpenBrace.Y;
            }
            if (textView.Highlight != null && textView.Highlight.CloseBrace.Y >= 0 && textView.Highlight.CloseBrace.Y < Document.TotalNumberOfLines)
            {
                num2 = textView.Highlight.CloseBrace.Y;
            }
            textView.Highlight = FindMatchingBracketHighlight();
            if (num >= 0)
            {
                UpdateLine(num);
            }
            if (num2 >= 0 && num2 != num)
            {
                UpdateLine(num2);
            }
            if (textView.Highlight != null)
            {
                int num3 = textView.Highlight.OpenBrace.Y;
                int num4 = textView.Highlight.CloseBrace.Y;
                if (num3 != num && num3 != num2)
                {
                    UpdateLine(num3);
                }
                if (num4 != num && num4 != num2 && num4 != num3)
                {
                    UpdateLine(num4);
                }
            }
        }

        public Highlight FindMatchingBracketHighlight()
        {
            if (Caret.Offset == 0)
            {
                return null;
            }
            foreach (BracketHighlightingSheme bracketsheme in bracketshemes)
            {
                Highlight highlight = bracketsheme.GetHighlight(Document, checked(Caret.Offset - 1));
                if (highlight != null)
                {
                    return highlight;
                }
            }
            return null;
        }

        public int GetVisibleColumnCount()
        {
            int num = 0;
            foreach (LineSegment item in Document.LineSegmentCollection)
            {
                int lineNumberForOffset = Document.GetLineNumberForOffset(item.Offset);
                if (Document.FoldingManager.IsLineVisible(lineNumberForOffset))
                {
                    num = Math.Max(num, TextView.GetVisualColumnFast(item, item.Length));
                }
            }
            return num;
        }

        public void SetDesiredColumn()
        {
            Caret.DesiredColumn = checked(TextView.GetDrawingXPos(Caret.Line, Caret.Column) + VirtualTop.X);
        }

        public void SetCaretToDesiredColumn()
        {
            Caret.Position = textView.GetLogicalColumn(Caret.Line, checked(Caret.DesiredColumn + VirtualTop.X), out var _);
        }

        public void OptionsChanged()
        {
            UpdateMatchingBracket();
            textView.OptionsChanged();
            caret.RecreateCaret();
            caret.UpdateCaretPosition();
            Document.GuidelinesManager.Update(this);
            Refresh();
        }

        public void HandleMouseWheel(MouseEventArgs e)
        {
            if ((Control.ModifierKeys & Keys.Control) != 0 && TextEditorProperties.MouseWheelTextZoom)
            {
                if (e.Delta > 0)
                {
                    motherTextEditorControl.Font = new Font(motherTextEditorControl.Font.Name, motherTextEditorControl.Font.Size + 1f);
                }
                else
                {
                    motherTextEditorControl.Font = new Font(motherTextEditorControl.Font.Name, Math.Max(6f, motherTextEditorControl.Font.Size - 1f));
                }
            }
            else
            {
                int num = Math.Abs(e.Delta) / 120;
                int val = checked((SystemInformation.MouseWheelScrollLines <= 0) ? (vScrollBar.Value - (TextEditorProperties.MouseWheelScrollDown ? 1 : (-1)) * Math.Sign(e.Delta) * vScrollBar.LargeChange) : (vScrollBar.Value - (TextEditorProperties.MouseWheelScrollDown ? 1 : (-1)) * Math.Sign(e.Delta) * SystemInformation.MouseWheelScrollLines * vScrollBar.SmallChange * num));
                vScrollBar.Value = Math.Max(vScrollBar.Minimum, Math.Min(vScrollBar.Maximum, val));
            }
        }

        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);
            if (DoHandleMousewheel)
            {
                HandleMouseWheel(e);
            }
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            Cursor = Cursors.Default;
            if (lastMouseInMargin != null)
            {
                lastMouseInMargin.HandleMouseLeave(EventArgs.Empty);
                lastMouseInMargin = null;
            }
            CloseToolTip();
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            mousepos = new Point(e.X, e.Y);
            if (e.Button == MouseButtons.Left)
            {
                mouseDownState = true;
            }
            foreach (AbstractMargin leftMargin in leftMargins)
            {
                if (leftMargin.DrawingPosition.Contains(e.X, e.Y))
                {
                    leftMargin.HandleMouseDown(new Point(e.X, e.Y), e.Button);
                }
            }
            base.OnMouseDown(e);
            CloseToolTip();
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            mouseDownState = false;
            base.OnMouseUp(e);
        }

        internal void ShowHiddenCursor(bool forceShow)
        {
            if (hiddenMouseCursor && (mouseCursorHidePosition != Cursor.Position || forceShow))
            {
                Cursor.Show();
                hiddenMouseCursor = false;
            }
        }

        private void SetToolTip(string text, int lineNumber)
        {
            if (toolTip == null || toolTip.IsDisposed)
            {
                toolTip = new DeclarationViewWindow(FindForm());
            }
            if (oldToolTip == text)
            {
                return;
            }
            if (text == null)
            {
                toolTip.Hide();
            }
            else
            {
                Point mousePosition = Control.MousePosition;
                Point point = PointToClient(mousePosition);
                if (lineNumber >= 0)
                {
                    lineNumber = Document.GetVisibleLine(lineNumber);
                    mousePosition.Y = checked(mousePosition.Y - point.Y + lineNumber * TextView.FontHeight - virtualTop.Y);
                }
                mousePosition.Offset(3, 3);
                toolTip.Owner = FindForm();
                toolTip.Location = mousePosition;
                toolTip.Description = text;
                toolTip.HideOnClick = true;
                toolTip.Show();
            }
            oldToolTip = text;
        }

        protected virtual void OnToolTipRequest(ToolTipRequestEventArgs e)
        {
            if (ToolTipRequest != null)
            {
                ToolTipRequest(this, e);
            }
        }

        protected virtual void CloseToolTip()
        {
            if (toolTipActive)
            {
                toolTipActive = false;
                SetToolTip(null, -1);
            }
            ResetMouseEventArgs();
        }

        protected override void OnMouseHover(EventArgs e)
        {
            base.OnMouseHover(e);
            if (Control.MouseButtons == MouseButtons.None)
            {
                RequestToolTip(PointToClient(Control.MousePosition));
            }
            else
            {
                CloseToolTip();
            }
        }

        protected void RequestToolTip(Point mousePos)
        {
            if (toolTipRectangle.Contains(mousePos))
            {
                if (!toolTipActive)
                {
                    ResetMouseEventArgs();
                }
                return;
            }
            checked
            {
                toolTipRectangle = new Rectangle(mousePos.X - 4, mousePos.Y - 4, 8, 8);
                TextLocation logicalPosition = textView.GetLogicalPosition(mousePos.X - textView.DrawingPosition.Left, mousePos.Y - textView.DrawingPosition.Top);
                bool flag = textView.DrawingPosition.Contains(mousePos) && logicalPosition.Y >= 0 && logicalPosition.Y < Document.TotalNumberOfLines;
                ToolTipRequestEventArgs toolTipRequestEventArgs = new ToolTipRequestEventArgs(mousePos, logicalPosition, flag);
                OnToolTipRequest(toolTipRequestEventArgs);
                if (toolTipRequestEventArgs.ToolTipShown)
                {
                    toolTipActive = true;
                    SetToolTip(toolTipRequestEventArgs.toolTipText, flag ? (logicalPosition.Y + 1) : (-1));
                }
                else
                {
                    CloseToolTip();
                }
            }
        }

        internal void RaiseMouseMove(MouseEventArgs e)
        {
            OnMouseMove(e);
        }

        internal void UpdateVirtualTop(Point value)
        {
            Point point = new Point(value.X, Math.Min(MaxVScrollValue, Math.Max(0, value.Y)));
            if (virtualTop != point)
            {
                virtualTop = point;
                motherTextAreaControl.VScrollBar.Value = virtualTop.Y;
                Invalidate();
            }
            caret.UpdateCaretPosition();
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (!toolTipRectangle.Contains(e.Location))
            {
                toolTipRectangle = Rectangle.Empty;
                if (toolTipActive)
                {
                    RequestToolTip(e.Location);
                }
            }
            if (Document.TextEditorProperties.ShowLineNumbers)
            {
                foreach (AbstractMargin leftMargin in leftMargins)
                {
                    if (!leftMargin.DrawingPosition.Contains(e.X, e.Y))
                    {
                        continue;
                    }
                    Cursor = leftMargin.Cursor;
                    leftMargin.HandleMouseMove(new Point(e.X, e.Y), e.Button);
                    if (lastMouseInMargin != leftMargin)
                    {
                        if (lastMouseInMargin != null)
                        {
                            lastMouseInMargin.HandleMouseLeave(EventArgs.Empty);
                        }
                        lastMouseInMargin = leftMargin;
                    }
                    return;
                }
            }
            if (lastMouseInMargin != null)
            {
                lastMouseInMargin.HandleMouseLeave(EventArgs.Empty);
                lastMouseInMargin = null;
            }
            if (textView.DrawingPosition.Contains(e.X, e.Y))
            {
                TextLocation logicalPosition = checked(TextView.GetLogicalPosition(e.X - TextView.DrawingPosition.X, e.Y - TextView.DrawingPosition.Y));
                if (SelectionManager.IsSelected(Document.PositionToOffset(logicalPosition)) && Control.MouseButtons == MouseButtons.None)
                {
                    if (Cursor != Cursors.Default)
                    {
                        Cursor = Cursors.Default;
                    }
                }
                else if (Cursor != textView.Cursor)
                {
                    Cursor = textView.Cursor;
                }
            }
            else
            {
                Cursor = Cursors.Default;
            }
        }

        public void Refresh(AbstractMargin margin)
        {
            updateMargin = margin;
            Invalidate(updateMargin.DrawingPosition);
            Update();
            updateMargin = null;
        }

        public void DrawImage(Graphics g)
        {
            int num = 0;
            int num2 = 0;
            bool flag = false;
            Rectangle rect = new Rectangle(0, 0, base.Width, base.Height);
            checked
            {
                if (backgroundImage != null)
                {
                    if (ImageLayout == ImageLayout.None)
                    {
                        int num3 = base.Width - backgroundImage.Width;
                        int num4 = base.Height - backgroundImage.Height;
                        int num5 = backgroundImage.Width;
                        int num6 = backgroundImage.Height;
                        g.DrawImage(rect: new Rectangle(num3, num4, num5, num6), image: backgroundImage);
                    }
                    else
                    {
                        g.DrawImage(backgroundImage, base.ClientRectangle, new Rectangle(0, 0, backgroundImage.Width, backgroundImage.Height), GraphicsUnit.Pixel);
                    }
                }
                bool flag2 = rect.X == 0 && rect.Y == 0 && rect.Width == base.Width && rect.Height == base.Height;
                g.TextRenderingHint = TextEditorProperties.TextRenderingHint;
                if (updateMargin != null)
                {
                    updateMargin.Paint(g, updateMargin.DrawingPosition);
                }
                if (rect.Width <= 0 || rect.Height <= 0)
                {
                    return;
                }
                foreach (AbstractMargin leftMargin in leftMargins)
                {
                    if (leftMargin.IsVisible)
                    {
                        Rectangle rectangle = new Rectangle(num, num2, leftMargin.Size.Width, base.Height - num2);
                        if (rectangle != leftMargin.DrawingPosition)
                        {
                            if (!flag2 && !rect.Contains(rectangle))
                            {
                                Invalidate();
                            }
                            flag = true;
                            leftMargin.DrawingPosition = rectangle;
                        }
                        num += leftMargin.DrawingPosition.Width;
                        if (rect.IntersectsWith(rectangle))
                        {
                            rectangle.Intersect(rect);
                            if (!rectangle.IsEmpty)
                            {
                                leftMargin.Paint(g, rectangle);
                            }
                        }
                    }
                    else if (leftMargin.GetType() == typeof(FoldMargin))
                    {
                        num += 8;
                    }
                }
                Rectangle rectangle2 = new Rectangle(num, num2, base.Width - num, base.Height - num2);
                if (rectangle2 != textView.DrawingPosition)
                {
                    flag = true;
                    textView.DrawingPosition = rectangle2;
                    BeginInvoke(new MethodInvoker(caret.UpdateCaretPosition));
                }
                if (rect.IntersectsWith(rectangle2))
                {
                    rectangle2.Intersect(rect);
                    if (!rectangle2.IsEmpty)
                    {
                        textView.Paint(g, rectangle2);
                    }
                }
                if (flag)
                {
                    motherTextAreaControl.AdjustScrollBars();
                }
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            int num = 0;
            int num2 = 0;
            bool flag = false;
            Graphics graphics = e.Graphics;
            Rectangle clipRectangle = e.ClipRectangle;
            checked
            {
                if (backgroundImage != null)
                {
                    if (ImageLayout == ImageLayout.None)
                    {
                        int num3 = base.Width - backgroundImage.Width;
                        int num4 = base.Height - backgroundImage.Height;
                        int num5 = backgroundImage.Width;
                        int num6 = backgroundImage.Height;
                        graphics.DrawImage(rect: new Rectangle(num3, num4, num5, num6), image: backgroundImage);
                    }
                    else
                    {
                        graphics.DrawImage(backgroundImage, base.ClientRectangle, new Rectangle(0, 0, backgroundImage.Width, backgroundImage.Height), GraphicsUnit.Pixel);
                    }
                }
                bool flag2 = clipRectangle.X == 0 && clipRectangle.Y == 0 && clipRectangle.Width == base.Width && clipRectangle.Height == base.Height;
                graphics.TextRenderingHint = TextEditorProperties.TextRenderingHint;
                if (updateMargin != null)
                {
                    updateMargin.Paint(graphics, updateMargin.DrawingPosition);
                }
                if (clipRectangle.Width <= 0 || clipRectangle.Height <= 0)
                {
                    return;
                }
                foreach (AbstractMargin leftMargin in leftMargins)
                {
                    if (leftMargin.IsVisible)
                    {
                        Rectangle rectangle = new Rectangle(num, num2, leftMargin.Size.Width, base.Height - num2);
                        if (rectangle != leftMargin.DrawingPosition)
                        {
                            if (!flag2 && !clipRectangle.Contains(rectangle))
                            {
                                Invalidate();
                            }
                            flag = true;
                            leftMargin.DrawingPosition = rectangle;
                        }
                        num += leftMargin.DrawingPosition.Width;
                        if (clipRectangle.IntersectsWith(rectangle))
                        {
                            rectangle.Intersect(clipRectangle);
                            if (!rectangle.IsEmpty)
                            {
                                leftMargin.Paint(graphics, rectangle);
                            }
                        }
                    }
                    else if (leftMargin.GetType() == typeof(FoldMargin))
                    {
                        num += 8;
                    }
                }
                Rectangle rectangle2 = new Rectangle(num, num2, base.Width - num, base.Height - num2);
                if (rectangle2 != textView.DrawingPosition)
                {
                    flag = true;
                    textView.DrawingPosition = rectangle2;
                    BeginInvoke(new MethodInvoker(caret.UpdateCaretPosition));
                }
                if (clipRectangle.IntersectsWith(rectangle2))
                {
                    rectangle2.Intersect(clipRectangle);
                    if (!rectangle2.IsEmpty)
                    {
                        textView.Paint(graphics, rectangle2);
                    }
                }
                if (flag)
                {
                    motherTextAreaControl.AdjustScrollBars();
                }
                base.OnPaint(e);
            }
        }

        private void DocumentFoldingsChanged(object sender, EventArgs e)
        {
            Document.GuidelinesManager.Clear(this);
            Caret.UpdateCaretPosition();
            Invalidate();
            motherTextAreaControl.AdjustScrollBars();
            Document.GuidelinesManager.Update(this);
        }

        protected internal virtual bool HandleKeyPress(char ch)
        {
            if (KeyEventHandler != null)
            {
                return KeyEventHandler(ch);
            }
            return false;
        }

        protected override bool IsInputChar(char charCode)
        {
            return true;
        }

        internal bool IsReadOnly(int offset)
        {
            if (Document.ReadOnly)
            {
                return true;
            }
            if (TextEditorProperties.SupportReadOnlySegments)
            {
                return Document.MarkerStrategy.GetMarkers(offset).Exists((TextMarker m) => m.IsReadOnly);
            }
            return false;
        }

        internal bool IsReadOnly(int offset, int length)
        {
            if (Document.ReadOnly)
            {
                return true;
            }
            if (TextEditorProperties.SupportReadOnlySegments)
            {
                return Document.MarkerStrategy.GetMarkers(offset, length).Exists((TextMarker m) => m.IsReadOnly);
            }
            return false;
        }

        public void SimulateKeyPress(char ch)
        {
            if (SelectionManager.HasSomethingSelected)
            {
                if (SelectionManager.SelectionIsReadonly)
                {
                    return;
                }
            }
            else if (IsReadOnly(Caret.Offset))
            {
                return;
            }
            if (ch < ' ')
            {
                return;
            }
            if (!hiddenMouseCursor && TextEditorProperties.HideMouseCursor && base.ClientRectangle.Contains(PointToClient(Cursor.Position)))
            {
                mouseCursorHidePosition = Cursor.Position;
                hiddenMouseCursor = true;
                Cursor.Hide();
            }
            CloseToolTip();
            BeginUpdate();
            Document.UndoStack.StartUndoGroup();
            try
            {
                if (!HandleKeyPress(ch))
                {
                    switch (Caret.CaretMode)
                    {
                        case CaretMode.InsertMode:
                            InsertChar(ch);
                            break;
                        case CaretMode.OverwriteMode:
                            ReplaceChar(ch);
                            break;
                        default:
                            //Debug.Assert(condition: false, "Unknown caret mode " + Caret.CaretMode);
                            break;
                    }
                }
                int line = Caret.Line;
                Document.FormattingStrategy.FormatLine(this, line, Document.PositionToOffset(Caret.Position), ch);
                EndUpdate();
            }
            finally
            {
                Document.UndoStack.EndUndoGroup();
            }
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            base.OnKeyPress(e);
            SimulateKeyPress(e.KeyChar);
            e.Handled = true;
        }

        public bool ExecuteDialogKey(Keys keyData)
        {
            if (DoProcessDialogKey != null && DoProcessDialogKey(keyData))
            {
                return true;
            }
            IEditAction editAction = motherTextEditorControl.GetEditAction(keyData);
            AutoClearSelection = true;
            if (editAction != null)
            {
                BeginUpdate();
                try
                {
                    lock (Document)
                    {
                        editAction.Execute(this);
                        if (AutoClearSelection && !selectionManager.IsMutilSelect && selectionManager.HasSomethingSelected && Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal)
                        {
                            SelectionManager.ClearSelection();
                        }
                    }
                }
                finally
                {
                    EndUpdate();
                    Caret.UpdateCaretPosition();
                }
                return true;
            }
            return false;
        }

        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (keyData == (Keys.Menu | Keys.Alt))
            {
                return ExecuteDialogKey(keyData) || true;
            }
            return ExecuteDialogKey(keyData) || base.ProcessDialogKey(keyData);
        }

        public void ScrollToCaret()
        {
            motherTextAreaControl.ScrollToCaret();
        }

        public void ScrollTo(int line)
        {
            motherTextAreaControl.ScrollTo(line);
        }

        public void BeginUpdate()
        {
            motherTextEditorControl.BeginUpdate();
        }

        public void EndUpdate()
        {
            motherTextEditorControl.EndUpdate();
        }

        private string GenerateWhitespaceString(int length)
        {
            return new string(' ', length);
        }

        public void InsertChar(char ch)
        {
            bool isInUpdate = motherTextEditorControl.IsInUpdate;
            if (!isInUpdate)
            {
                BeginUpdate();
            }
            if (char.IsWhiteSpace(ch) && ch != '\t' && ch != '\n')
            {
                ch = ' ';
            }
            Document.UndoStack.StartUndoGroup();
            checked
            {
                if (SelectionManager.IsMutilSelect)
                {
                    if (selectionManager.HasSomethingMutilLinesSeleted)
                    {
                        Delete.DeleteSelection(this);
                    }
                    TextLocation textLocation = new TextLocation(SelectionManager.SelectionStart.Column, SelectionManager.SelectionStart.Line);
                    TextLocation textLocation2 = new TextLocation(SelectionManager.SelectionEnd.Column, SelectionManager.SelectionEnd.Line);
                    List<ISelection> list = new List<ISelection>();
                    foreach (ISelection item in selectionManager.selectionCollection)
                    {
                        TextLocation startPosition = new TextLocation(item.StartPosition.Column, item.StartPosition.Line);
                        TextLocation endPosition = new TextLocation(item.EndPosition.Column, item.EndPosition.Line);
                        list.Add(new NewLineSelection(Document, startPosition, endPosition));
                    }
                    foreach (ISelection item2 in list)
                    {
                        LineSegment lineSegment = Document.GetLineSegment(item2.StartPosition.Line);
                        int offset = Document.PositionToOffset(item2.StartPosition);
                        int column = item2.StartPosition.Column;
                        if (lineSegment.Length < column && ch != '\n')
                        {
                            Document.Insert(offset, GenerateWhitespaceString(column - lineSegment.Length) + ch);
                        }
                        else
                        {
                            Document.Insert(offset, ch.ToString());
                        }
                        item2.StartPosition = new TextLocation(item2.StartPosition.Column + 1, item2.StartPosition.Line);
                        item2.EndPosition = new TextLocation(item2.StartPosition.Column, item2.EndPosition.Line);
                    }
                    SelectionManager.SelectionStart = new TextLocation(SelectionManager.SelectionStart.Column + 1, SelectionManager.SelectionStart.Line);
                    SelectionManager.SelectionEnd = new TextLocation(SelectionManager.SelectionEnd.Column + 1, SelectionManager.SelectionEnd.Line);
                    SelectionManager.selectionCollection = list;
                }
                else
                {
                    if (Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal && SelectionManager.SelectionCollection.Count > 0)
                    {
                        Caret.Position = SelectionManager.SelectionCollection[0].StartPosition;
                        SelectionManager.RemoveSelectedText();
                    }
                    LineSegment lineSegment2 = Document.GetLineSegment(Caret.Line);
                    int offset2 = Caret.Offset;
                    int column2 = Caret.Column;
                    if (lineSegment2.Length < column2 && ch != '\n')
                    {
                        Document.Insert(offset2, GenerateWhitespaceString(column2 - lineSegment2.Length) + ch);
                    }
                    else
                    {
                        Document.Insert(offset2, ch.ToString());
                    }
                }
                Document.UndoStack.EndUndoGroup();
                Caret.Column++;
                if (!isInUpdate)
                {
                    EndUpdate();
                    UpdateLineToEnd(Caret.Line, Caret.Column);
                }
            }
        }

        public void InsertString(string str, bool paste = false)
        {
            bool isInUpdate = motherTextEditorControl.IsInUpdate;
            if (!isInUpdate)
            {
                BeginUpdate();
            }
            checked
            {
                try
                {
                    Document.UndoStack.StartUndoGroup();
                    int num = 0;
                    int num2 = 0;
                    if (SelectionManager.IsMutilSelect)
                    {
                        if (Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal && SelectionManager.SelectionCollection.Count > 0)
                        {
                            TextLocation selectionStart = new TextLocation(SelectionManager.SelectionStart.Column, SelectionManager.SelectionStart.Line);
                            TextLocation selectionEnd = new TextLocation(SelectionManager.SelectionEnd.Column, SelectionManager.SelectionEnd.Line);
                            if (str == "\t")
                            {
                                foreach (ISelection item in SelectionManager.SelectionCollection)
                                {
                                    Caret.Position = item.StartPosition;
                                    num = Document.PositionToOffset(Caret.Position);
                                    num2 = Caret.Line;
                                    int num3 = Document.PositionToOffset(item.StartPosition);
                                    int num4 = Document.PositionToOffset(item.EndPosition);
                                    LineSegment lineSegment = Document.GetLineSegment(Caret.Line);
                                    if (lineSegment.Length < Caret.Column)
                                    {
                                        int num5 = Caret.Column - lineSegment.Length;
                                        Document.Insert(num, GenerateWhitespaceString(num5) + str);
                                        Caret.Position = Document.OffsetToPosition(num + str.Length + num5);
                                        num3 = num3 + str.Length + num5;
                                        num4 = num4 + str.Length + num5;
                                    }
                                    else
                                    {
                                        Document.Insert(num, str);
                                        Caret.Position = Document.OffsetToPosition(num + str.Length);
                                        num3 += str.Length;
                                        num4 += str.Length;
                                    }
                                    item.StartPosition = new TextLocation(Document.OffsetToPosition(num3).Column, item.StartPosition.Line);
                                    item.EndPosition = new TextLocation(Document.OffsetToPosition(num4).Column, item.EndPosition.Line);
                                    if (item.StartPosition.Column > selectionStart.Column)
                                    {
                                        selectionStart = new TextLocation(item.StartPosition.Column, SelectionManager.SelectionStart.Line);
                                    }
                                    if (item.EndPosition.Column > selectionEnd.Column)
                                    {
                                        selectionEnd = new TextLocation(item.EndPosition.Column, SelectionManager.SelectionEnd.Line);
                                    }
                                }
                            }
                            else if (!paste && selectionManager.selectionCollection.Count > 0)
                            {
                                foreach (ISelection item2 in SelectionManager.SelectionCollection)
                                {
                                    Caret.Position = item2.StartPosition;
                                    num = Document.PositionToOffset(Caret.Position);
                                    num2 = Caret.Line;
                                    int num6 = Document.PositionToOffset(item2.StartPosition);
                                    int num7 = Document.PositionToOffset(item2.EndPosition);
                                    LineSegment lineSegment2 = Document.GetLineSegment(Caret.Line);
                                    if (lineSegment2.Length < Caret.Column)
                                    {
                                        int num8 = Caret.Column - lineSegment2.Length;
                                        Document.Insert(num, GenerateWhitespaceString(num8) + str);
                                        Caret.Position = Document.OffsetToPosition(num + str.Length + num8);
                                        num6 = num6 + str.Length + num8;
                                        num7 = num7 + str.Length + num8;
                                    }
                                    else
                                    {
                                        Document.Insert(num, str);
                                        Caret.Position = Document.OffsetToPosition(num + str.Length);
                                        num6 += str.Length;
                                        num7 += str.Length;
                                    }
                                    item2.StartPosition = new TextLocation(Document.OffsetToPosition(num6).Column, item2.StartPosition.Line);
                                    item2.EndPosition = new TextLocation(Document.OffsetToPosition(num7).Column, item2.EndPosition.Line);
                                    if (item2.StartPosition.Column > selectionStart.Column)
                                    {
                                        selectionStart = new TextLocation(item2.StartPosition.Column, SelectionManager.SelectionStart.Line);
                                    }
                                    if (item2.EndPosition.Column > selectionEnd.Column)
                                    {
                                        selectionEnd = new TextLocation(item2.EndPosition.Column, SelectionManager.SelectionEnd.Line);
                                    }
                                }
                            }
                            else
                            {
                                num = Document.PositionToOffset(Caret.Position);
                                num2 = Caret.Line;
                                LineSegment lineSegment3 = Document.GetLineSegment(Caret.Line);
                                if (lineSegment3.Length < Caret.Column)
                                {
                                    int num9 = Caret.Column - lineSegment3.Length;
                                    Document.Insert(num, GenerateWhitespaceString(num9) + str);
                                    Caret.Position = Document.OffsetToPosition(num + str.Length + num9);
                                }
                                else
                                {
                                    Document.Insert(num, str);
                                    Caret.Position = Document.OffsetToPosition(num + str.Length);
                                }
                                selectionStart = new TextLocation(Caret.Position.Column, selectionStart.Line);
                                selectionEnd = new TextLocation(Caret.Position.Column, selectionEnd.Line);
                            }
                            SelectionManager.SelectionStart = selectionStart;
                            SelectionManager.SelectionEnd = selectionEnd;
                        }
                    }
                    else
                    {
                        if (Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal && SelectionManager.SelectionCollection.Count > 0)
                        {
                            Caret.Position = SelectionManager.SelectionCollection[0].StartPosition;
                            SelectionManager.RemoveSelectedText();
                        }
                        num = Document.PositionToOffset(Caret.Position);
                        num2 = Caret.Line;
                        LineSegment lineSegment4 = Document.GetLineSegment(Caret.Line);
                        if (lineSegment4.Length < Caret.Column)
                        {
                            int num10 = Caret.Column - lineSegment4.Length;
                            Document.Insert(num, GenerateWhitespaceString(num10) + str);
                            Caret.Position = Document.OffsetToPosition(num + str.Length + num10);
                        }
                        else
                        {
                            Document.Insert(num, str);
                            Caret.Position = Document.OffsetToPosition(num + str.Length);
                        }
                    }
                    Document.UndoStack.EndUndoGroup();
                    if (num2 != Caret.Line)
                    {
                        UpdateToEnd(num2);
                    }
                    else
                    {
                        UpdateLineToEnd(Caret.Line, Caret.Column);
                    }
                }
                finally
                {
                    if (!isInUpdate)
                    {
                        EndUpdate();
                    }
                }
            }
        }

        public void ReplaceChar(char ch)
        {
            bool isInUpdate = motherTextEditorControl.IsInUpdate;
            if (!isInUpdate)
            {
                BeginUpdate();
            }
            if (Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal && SelectionManager.SelectionCollection.Count > 0)
            {
                Caret.Position = SelectionManager.SelectionCollection[0].StartPosition;
                SelectionManager.RemoveSelectedText();
            }
            int line = Caret.Line;
            LineSegment lineSegment = Document.GetLineSegment(line);
            int num = Document.PositionToOffset(Caret.Position);
            checked
            {
                if (num < lineSegment.Offset + lineSegment.Length)
                {
                    Document.Replace(num, 1, ch.ToString());
                }
                else
                {
                    Document.Insert(num, ch.ToString());
                }
                if (!isInUpdate)
                {
                    EndUpdate();
                    UpdateLineToEnd(line, Caret.Column);
                }
                Caret.Column++;
            }
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            if (!disposing || disposed)
            {
                return;
            }
            disposed = true;
            if (caret != null)
            {
                caret.PositionChanged -= SearchMatchingBracket;
                caret.Dispose();
            }
            if (selectionManager != null)
            {
                selectionManager.Dispose();
            }
            Document.TextContentChanged -= TextContentChanged;
            Document.FoldingManager.FoldingsChanged -= DocumentFoldingsChanged;
            motherTextAreaControl = null;
            motherTextEditorControl = null;
            foreach (AbstractMargin leftMargin in leftMargins)
            {
                if (leftMargin is IDisposable)
                {
                    (leftMargin as IDisposable).Dispose();
                }
            }
            textView.Dispose();
        }

        internal void UpdateLine(int line)
        {
            UpdateLines(0, line, line);
        }

        internal void UpdateLines(int lineBegin, int lineEnd)
        {
            UpdateLines(0, lineBegin, lineEnd);
        }

        internal void UpdateToEnd(int lineBegin)
        {
            lineBegin = Document.GetVisibleLine(lineBegin);
            checked
            {
                int num = Math.Max(0, lineBegin * textView.FontHeight);
                num = Math.Max(0, num - virtualTop.Y);
                Rectangle rc = new Rectangle(0, num, base.Width, base.Height - num);
                Invalidate(rc);
            }
        }

        internal void UpdateLineToEnd(int lineNr, int xStart)
        {
            UpdateLines(xStart, lineNr, lineNr);
        }

        internal void UpdateLine(int line, int begin, int end)
        {
            UpdateLines(line, line);
        }

        internal void UpdateLines(int xPos, int lineBegin, int lineEnd)
        {
            InvalidateLines(checked(xPos * TextView.WideSpaceWidth), lineBegin, lineEnd);
        }

        private void InvalidateLines(int xPos, int lineBegin, int lineEnd)
        {
            lineBegin = Math.Max(Document.GetVisibleLine(lineBegin), FirstPhysicalLine);
            checked
            {
                lineEnd = Math.Min(Document.GetVisibleLine(lineEnd), FirstPhysicalLine + textView.VisibleLineCount);
                int num = Math.Max(0, lineBegin * textView.FontHeight);
                int num2 = Math.Min(textView.DrawingPosition.Height, (1 + lineEnd - lineBegin) * (textView.FontHeight + 1));
                Rectangle rc = new Rectangle(0, num - 1 - virtualTop.Y, base.Width, num2 + 3);
                Invalidate(rc);
            }
        }

        internal void DoShowContextMenuHandler(EventArgs e)
        {
            EventHandler eventHandler = (EventHandler)base.Events[showContextMenuEventObject];
            if (showContextMenuEventObject != null)
            {
                eventHandler?.Invoke(this, e);
            }
        }

        public string GetWordBeforeCaret()
        {
            int num = TextUtilities.FindPrevWordStart(Document, Caret.Offset);
            return Document.GetText(num, checked(Caret.Offset - num));
        }
    }
}
